package com.eian.boot.module.system.log.service;

import com.eian.boot.common.core.utils.BeanCopierUtils;
import com.eian.boot.common.core.utils.Ip2RegionUtil;
import com.eian.boot.common.util.ServletUtil;
import com.eian.boot.common.util.UserAgentParser;
import com.eian.boot.module.system.log.mapper.SysLoginLogMapper;
import com.eian.boot.module.system.log.model.dto.LoginLogDTO;
import com.eian.boot.module.system.log.model.dto.LoginLogQueryRequest;
import com.eian.boot.module.system.log.model.entity.SysLoginLogEntity;
import com.eian.boot.module.system.log.model.vo.LoginLogDetailVO;
import com.eian.boot.module.system.log.model.vo.LoginLogVO;
import com.eian.boot.mybatis.core.page.PageResult;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryChain;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 系统登录日志服务
 *
 * @author alex.meng
 */
@Slf4j
@Service
public class SysLoginLogService extends com.eian.boot.mybatis.core.service.BaseService<SysLoginLogMapper, SysLoginLogEntity> {

    /**
     * 记录登录日志（异步）
     */
    @Async
    public void recordLoginLog(LoginLogDTO loginLogDTO) {
        try {
            SysLoginLogEntity logEntity = SysLoginLogEntity.builder()
                    .traceId(MDC.get("traceId"))
                    .userId(loginLogDTO.getUserId())
                    .username(loginLogDTO.getUsername())
                    .loginType(loginLogDTO.getLoginType())
                    .loginStatus(loginLogDTO.getLoginStatus())
                    .loginIp(loginLogDTO.getLoginIp())
                    .msg(loginLogDTO.getMsg())
                    .token(loginLogDTO.getToken())
                    .build();

            // 解析IP归属地
            if (StringUtils.isNotBlank(loginLogDTO.getLoginIp())) {
                try {
                    logEntity.setLoginLocation(Ip2RegionUtil.getAddressByIp(loginLogDTO.getLoginIp()));
                } catch (Exception e) {
                    logEntity.setLoginLocation("未知");
                }
            }

            // 解析User-Agent
            String userAgent = ServletUtil.getUserAgent();
            if (StringUtils.isNotBlank(userAgent)) {
                logEntity.setUserAgent(userAgent);
                logEntity.setBrowser(UserAgentParser.parseBrowser(userAgent));
                logEntity.setOs(UserAgentParser.parseOS(userAgent));
            }

            this.save(logEntity);
        } catch (Exception e) {
            log.error("保存登录日志失败", e);
        }
    }

    /**
     * 分页查询登录日志
     * 应用数据权限控制，基于用户过滤
     */
    @com.eian.boot.common.annotation.DataScope(userAlias = "t_sys_login_log")
    public PageResult<LoginLogVO> queryLoginLogs(LoginLogQueryRequest request) {
        QueryChain<SysLoginLogEntity> queryChain = this.queryChain();

        if (StringUtils.isNotBlank(request.getUsername())) {
            queryChain.like(SysLoginLogEntity::getUsername, request.getUsername());
        }
        if (request.getLoginStatus() != null) {
            queryChain.eq(SysLoginLogEntity::getLoginStatus, request.getLoginStatus());
        }
        if (request.getLoginType() != null) {
            queryChain.eq(SysLoginLogEntity::getLoginType, request.getLoginType());
        }
        if (StringUtils.isNotBlank(request.getLoginIp())) {
            queryChain.like(SysLoginLogEntity::getLoginIp, request.getLoginIp());
        }
        if (request.getStartTime() != null) {
            queryChain.ge(SysLoginLogEntity::getCreatedAt, request.getStartTime());
        }
        if (request.getEndTime() != null) {
            queryChain.le(SysLoginLogEntity::getCreatedAt, request.getEndTime());
        }
        queryChain.orderBy(SysLoginLogEntity::getCreatedAt, false);

        Page<SysLoginLogEntity> page = queryChain.page(
                Page.of(request.getCurrent(), request.getPageSize())
        );

        List<LoginLogVO> voList = BeanCopierUtils.copyList(page.getRecords(), LoginLogVO.class);
        return PageResult.build(voList, page.getTotalRow());
    }

    /**
     * 获取登录日志详情
     */
    public LoginLogDetailVO getLoginLogDetail(Long id) {
        SysLoginLogEntity entity = this.getById(id);
        return BeanCopierUtils.copy(entity, LoginLogDetailVO.class);
    }

    /**
     * 批量删除登录日志（物理删除）
     */
    public void deleteLoginLogs(List<Long> ids) {
        if (ids != null && !ids.isEmpty()) {
            this.removeByIds(ids);
        }
    }

    /**
     * 获取登录失败次数（用于账号锁定策略）
     */
    public int getLoginFailCount(String username, int minutes) {
        LocalDateTime startTime = LocalDateTime.now().minusMinutes(minutes);

        Long count = this.queryChain()
                .eq(SysLoginLogEntity::getUsername, username)
                .eq(SysLoginLogEntity::getLoginStatus, 0) // 0-失败
                .ge(SysLoginLogEntity::getCreatedAt, startTime)
                .count();

        return count != null ? count.intValue() : 0;
    }
}

